package com.ruoyi.quartz.task;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.domain.*;
import com.ruoyi.system.domain.vo.StockRealTimeChange;
import com.ruoyi.system.service.*;
import com.ruoyi.system.service.h5.IHomeService;
import com.ruoyi.system.service.h5.MiniDailyReplayService;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Component;
import com.ruoyi.common.utils.StringUtils;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Time;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.Year;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 定时任务调度测试
 *
 * @author ruoyi
 */
@Component("ryTask")
@Slf4j
public class RyTask
{
    private static final Logger logger = LoggerFactory.getLogger(RyTask.class);

    @Autowired
    private IMiniStockService miniStockService;
    @Autowired
    private IMiniSubjectService miniSubjectService;
    @Autowired
    private MiniStockSubjectService miniStockSubjectService;
    @Autowired
    private MiniSubjectHistoryService miniSubjectHistoryService;
    @Autowired
    private ApiProfitabilityService apiProfitabilityService;
    @Autowired
    private ApiScoreReportService apiScoreReportService;
    @Autowired
    private ApiDebtPayAbilityService apiDebtPayAbilityService;
    @Autowired
    private ApiProfitSegmentationService apiProfitSegmentationService;
    @Autowired
    private MiniDailyReplayService miniDailyReplayService;
    @Autowired
    private ApiAchievementsReportService apiAchievementsReportService;
    @Autowired
    private ApiMoneyInflowTrendService apiMoneyInflowTrendService;
    @Autowired
    private ApiStageMaxMinService apiStageMaxMinService;
    private RestTemplate restTemplate;
    @Autowired
    private IHomeService iHomeService;

    public RyTask(RestTemplateBuilder restTemplateBuilder) {
        RestTemplate template = restTemplateBuilder.build();
        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Arrays.asList(
                MediaType.TEXT_HTML,
                MediaType.TEXT_PLAIN));
        template.getMessageConverters().add(mappingJackson2HttpMessageConverter);
        this.restTemplate = template;
    }
    public void ryMultipleParams(String s, Boolean b, Long l, Double d, Integer i)
    {
        System.out.println(StringUtils.format("执行多参方法： 字符串类型{}，布尔类型{}，长整型{}，浮点型{}，整形{}", s, b, l, d, i));
    }

    public void ryParams(String params)
    {
        System.out.println("执行有参方法：" + params);
    }

    public void ryNoParams()
    {
        System.out.println("执行无参方法");
    }

    public void getStockRealTimeChange(String stockNo){
        MiniStock in = new MiniStock();
        in.setStockNo(stockNo);
        List<MiniStock> stockList = miniStockService.selectMiniStockListNotGroup(in).stream().filter(it -> StringUtils.isNotEmpty(it.getSubjectIds()))
                .sorted(Comparator.comparing(MiniStock::getLevel).reversed()).collect(Collectors.toList());
        Integer maxLevel = stockList.get(0).getLevel();
        logger.info("最大层级是:"+ maxLevel);
        List<MiniStock> updateStockList = new ArrayList<>();
        for (MiniStock stock : stockList) {
            String url = String.format("http://api.mairuiapi.com/hsrl/ssjy/%s/%s", stock.getStockNo(), Constants.STOCK_API_KEY);
            StockRealTimeChange result = null;
            try {
                result = restTemplate.getForObject(url, StockRealTimeChange.class);
            } catch (Exception e) {
                log.info("getStockRealTimeChange error url:{},error:{}",url, e.getMessage());
                if (e.getMessage().contains("101")){
                    return;
                }
            }
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            // StockRealTimeChange result = new StockRealTimeChange();
            // result.setPc(BigDecimal.valueOf(ThreadLocalRandom.current().nextFloat() * 21 - 10).setScale(2, RoundingMode.HALF_UP));
            // result.setP(BigDecimal.valueOf(ThreadLocalRandom.current().nextFloat() * 40).setScale(2, RoundingMode.HALF_UP));
            if (result == null){
                continue;
            }
            stock.setRise(result.getPc());
            stock.setPrice(result.getP());
            stock.setFlowMarketValue(result.getLt());
            stock.setTotalMarketValue(result.getSz());
            stock.setPriceEarningsRatio(result.getPe());
            stock.setTurnoverRate(result.getHs());
            final MiniStock updateStock = new MiniStock(stock.getId(), result.getPc(), result.getP(), result.getLt(), result.getSz(), result.getPe(), result.getHs());
            logger.info("stockNo:{},result:{}",stock.getStockNo(), JSON.toJSONString(result));
            if (updateStock.getRise()!=null){
                logger.info("stockNo:{} pass updateCheck",stock.getStockNo());
                updateStockList.add(updateStock);
            }
        }
        if (CollUtil.isNotEmpty(updateStockList)){
            miniStockService.updateBatchById(updateStockList);
        }
        miniSubjectService.updateAllRateZero();

        List<MiniSubject> updateSubjectList = new ArrayList<>();
        Map<Long, List<MiniStock>> subjectIdMap = stockList.stream().collect(Collectors.groupingBy(it->Long.valueOf(it.getSubjectIds())));
        for (Map.Entry<Long, List<MiniStock>> entry : subjectIdMap.entrySet()) {
            List<MiniStock> temList = entry.getValue().stream().filter(x->x.getRise()!=null).collect(Collectors.toList());
            if (CollUtil.isEmpty(temList)){
                continue;
            }
            BigDecimal totalRise = temList.stream()
                    .map(MiniStock::getRise)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            int stockCount = temList.size();
            int stockRiseCount = (int) temList.stream().filter(it->it.getRise().compareTo(BigDecimal.valueOf(10))>=0).count();
            BigDecimal averageRise = totalRise.divide(BigDecimal.valueOf(stockCount), 2, RoundingMode.HALF_UP);
            updateSubjectList.add(new MiniSubject(entry.getKey(),averageRise,stockCount,stockRiseCount));
        }
        logger.info("待更新的题材数量："+ updateSubjectList.size());
        if (CollUtil.isNotEmpty(updateSubjectList)) {
            miniSubjectService.batchUpdateRate(updateSubjectList);

            dealParentSubjectRise(maxLevel);

        }
    }
    private void dealParentSubjectRise(int level) {
        if (level==0){
            return;
        }
        List<MiniSubject> parentSubjectList = miniSubjectService.getParentRate(level);
        miniSubjectService.batchUpdateRate(parentSubjectList);
        dealParentSubjectRise(level-1);
    }

    public void getStockRealTimeChange(){
        getStockRealTimeChange(null);
    }

    /**
     * 每日轮动 题材历史记录
     */
    public void saveSubjectHistory(){
        miniSubjectHistoryService.deleteYestdayHistory();
        List<MiniSubjectHistory> historyList = miniSubjectService.selectSubjectHistory();
        miniSubjectHistoryService.saveBatch(historyList);
        Integer maxLevel = historyList.stream().sorted(Comparator.comparing(MiniSubjectHistory::getLevel).reversed()).collect(Collectors.toList()).get(0).getLevel();

        dealParentSubjectMoneyInflow(maxLevel);
    }

    private void dealParentSubjectMoneyInflow(int level) {
        if (level==0){
            return;
        }
        List<MiniSubjectHistory> parentSubjectList = miniSubjectService.getParentRateMoneyInflow(level);
        miniSubjectHistoryService.batchUpdatetMoneyInflow(parentSubjectList);
        dealParentSubjectMoneyInflow(level-1);
    }

    /**
     * 获取财务排名数据  api盈利能力
     * @param year 年份
     * @param quarter 季度 1,2,3,4
     */
    public void getProfitability(String year, String quarter){
        List<ApiProfitability> list = apiProfitabilityService.list(Wrappers.<ApiProfitability>lambdaQuery().eq(ApiProfitability::getY, year)
                .eq(ApiProfitability::getQ, quarter)
                .last("limit 1"));
        if (CollUtil.isNotEmpty(list)){
            return;
        }
        String url = String.format("http://api.mairuiapi.com/hicw/yl/%s/%s/%s", year,quarter, Constants.STOCK_API_KEY);
        ApiProfitability[] result = restTemplate.getForObject(url, ApiProfitability[].class);
        apiProfitabilityService.saveBatch(ListUtil.toList(result));
    }
    /**
     * 获取财务排名数据  api业绩快报
     * @param year 年份
     * @param quarter 季度 1,2,3,4
     */
    public void getScoreReport(String year, String quarter){
        List<ApiScoreReport> list = apiScoreReportService.list(Wrappers.<ApiScoreReport>lambdaQuery().eq(ApiScoreReport::getY, year)
                .eq(ApiScoreReport::getQ, quarter)
                .last("limit 1"));
        if (CollUtil.isNotEmpty(list)){
            return;
        }
        String url = String.format("http://api.mairuiapi.com/hicw/yjkb/%s/%s/%s", year,quarter, Constants.STOCK_API_KEY);
        ApiScoreReport[] result = restTemplate.getForObject(url, ApiScoreReport[].class);
        apiScoreReportService.saveBatch(ListUtil.toList(result));
    }
    /**
     * 获取财务排名数据  api偿债能力
     * @param year 年份
     * @param quarter 季度 1,2,3,4
     */
    public void getDeptPayAbility(String year, String quarter){
        List<ApiDebtPayAbility> list = apiDebtPayAbilityService.list(Wrappers.<ApiDebtPayAbility>lambdaQuery().eq(ApiDebtPayAbility::getY, year)
                .eq(ApiDebtPayAbility::getQ, quarter)
                .last("limit 1"));
        if (CollUtil.isNotEmpty(list)){
            return;
        }
        String url = String.format("http://api.mairuiapi.com/hicw/cznl/%s/%s/%s", year,quarter, Constants.STOCK_API_KEY);
        ApiDebtPayAbility[] result = restTemplate.getForObject(url, ApiDebtPayAbility[].class);
        apiDebtPayAbilityService.saveBatch(ListUtil.toList(result));
    }
    /**
     * 获取个股详情里面的数据 api利润细分
     */
    public void getProfitSegmentation(){
        apiProfitSegmentationService.remove(Wrappers.lambdaQuery());
        String url = String.format("http://api.mairuiapi.com/hicw/lr/%s", Constants.STOCK_API_KEY);
        ApiProfitSegmentation[] result = restTemplate.getForObject(url, ApiProfitSegmentation[].class);
        apiProfitSegmentationService.saveBatch(ListUtil.toList(result));
    }
    /**
     * 每日复盘--涨停股票
     */
    public void getDailyReplay(){
        LocalDate today = LocalDate.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String day = today.format(formatter);
        miniDailyReplayService.remove(Wrappers.<MiniDailyReplay>lambdaQuery().eq(MiniDailyReplay::getReplayDay,day));
        String url = String.format("http://api.mairuiapi.com/hslt/ztgc/%s/%s", day, Constants.STOCK_API_KEY);
        MiniDailyReplay[] result = restTemplate.getForObject(url, MiniDailyReplay[].class);
        if (result == null){
            return;
        }
        List<MiniDailyReplay> list = Arrays.asList(result);
        list.forEach(it->{
            it.setReplayDay(day);
            it.setLiutong(it.getLt());
            it.setDm(it.getDm().replace("sz", "").replace("sh",""));
        });
        miniDailyReplayService.saveBatch(list);
    }
    public void getAchievementsReport(){
        int startYear = 2023;
        int startQuarter = 4;

        int endYear = 2010;
        int endQuarter = 1;

        for (int year = startYear; year >= endYear; year--) {
            int quarterStart = year == startYear ? startQuarter : 4;
            int quarterEnd = year == endYear ? endQuarter - 1 : 0;

            for (int quarter = quarterStart; quarter > quarterEnd; quarter--) {
                getAchievementsReport(year+"", quarter+"");
            }
        }
    }
    /**
     * 财务排名，取业绩报表的数据
     */
    public void getAchievementsReport(String year, String quarter){
        List<ApiAchievementsReport> list = apiAchievementsReportService.list(Wrappers.<ApiAchievementsReport>lambdaQuery().eq(ApiAchievementsReport::getY, year)
                .eq(ApiAchievementsReport::getQ, quarter)
                .last("limit 1"));
        if (CollUtil.isNotEmpty(list)){
            return;
        }
        String url = String.format("http://api.mairuiapi.com/hicw/yjbb/%s/%s/%s", year,quarter, Constants.STOCK_API_KEY);
        ApiAchievementsReport[] result = restTemplate.getForObject(url, ApiAchievementsReport[].class);
        apiAchievementsReportService.saveBatch(ListUtil.toList(result));
    }
    /**
     * 沪深基础数据API文档-资金流-资金流入趋势
     * api限制每分钟只能访问20次，那么每五分钟取20个来入库
     */
    public void getMoneyInflowTrend(){
        // 获取昨天日期
        LocalDate yesterday = LocalDate.now().minusDays(1);
        // 创建日期格式化对象
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        // 格式化昨天日期
        String yesterdayStr = yesterday.format(formatter);
        List<String> stockNoList = miniStockSubjectService.selectStockNotGetMoneyInflow(yesterdayStr);
        List<ApiMoneyInflowTrend> insertList = new ArrayList<>();
        if (CollUtil.isNotEmpty(stockNoList)){
            for (String stockNo : stockNoList) {
                try {
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                String url = String.format("http://api.mairuiapi.com/hsmy/zjlr/%s/%s", stockNo, Constants.STOCK_API_KEY);
                ApiMoneyInflowTrend[] result = restTemplate.getForObject(url, ApiMoneyInflowTrend[].class);
                if (result!=null&&result.length>0) {
                    for (int i = 0; i < 1; i++) {
                        ApiMoneyInflowTrend insert = result[i];
                        insert.setStockNo(stockNo);
                        insertList.add(insert);
                    }
                }
            }
            apiMoneyInflowTrendService.saveBatch(insertList);
        }
    }

    /**
     * 沪深分析数据API文档-市场表现-阶段最高最低
     * 数据更新：每天20:00（约10分钟完成更新）
     */
    public void getStockStageMaxMin(){
        String url = String.format("http://api.mairuiapi.com/himk/jdzgzd/%s", Constants.STOCK_API_KEY);
        ApiStageMaxMin[] result = restTemplate.getForObject(url, ApiStageMaxMin[].class);
        if (result!=null){
            String t = result[0].getT();
            ApiStageMaxMin one = apiStageMaxMinService.getOne(Wrappers.<ApiStageMaxMin>lambdaQuery().eq(ApiStageMaxMin::getT, t).last("limit 1"));
            if (Objects.isNull(one)){
                List<ApiStageMaxMin> list = Arrays.asList(result);
                list.forEach(it->{
                    String dm = it.getDm();
                    // 获取前两个字符
                    it.setDmPrefix(dm.substring(0, 2));
                    // 获取从第三个字符开始的子串
                    it.setDm(dm.substring(2));
                });
                apiStageMaxMinService.saveBatch(list);
            }
        }
    }

    public void refreshMainSubject(){
        iHomeService.refreshMainSubject();
    }
}
